﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;

namespace winpackman
{
    public partial class dataupdate : Form
    {
        #region packages file structure
        const int PACK_ID = 0;
        const int PACK_CATEGORY = 1;
        const int PACK_NAME = 2;
        const int PACK_VERSION = 3;
        const int PACK_DESCRIPTION = 4;
        const int PACK_FILETYPE = 5;
        const int PACK_VERSIONTYPE = 6;
        const int PACK_DEPENDENCY = 7;
        #endregion
        #region packages language structure
        const int LANG_MEMBEROF_PACK = 0;
        const int LANG_ARCHITECTURE = 1;
        const int LANG_FILEURL = 2;
        const int LANG_INSTALLARGUMENTS = 3;
        const int LANG_FILEMD5 = 4;
        const int LANG_INSTALLED = 5;
        #endregion

        WebClient client = new WebClient();

        public winpackman_class main_class = new winpackman_class();

        public Dictionary<int, downloadlist> Downloadlistdata = new Dictionary<int, downloadlist> { };
        public Dictionary<int, listbox> listboxdata = new Dictionary<int, listbox> { };

        public bool load = false;

        int downloading = -2;

        DateTime start = DateTime.Now;

        public dataupdate()
        {
            InitializeComponent();
        }

        private void dataupdate_Load(object sender, EventArgs e)
        {
            if (!Directory.Exists("Cache")) Directory.CreateDirectory("Cache");
            backgroundWorker1.RunWorkerAsync();
        }


        int addtodo(int count, string url, string filename, string name)
        {
            downloadlist downlaoditem = new downloadlist();
            downlaoditem.filename = filename;
            downlaoditem.URL = new Uri(url);
            Downloadlistdata.Add(count, downlaoditem);
            listbox listboxitem = new listbox();
            listboxitem.name = "Download " + name + " list";
            listboxitem.downloaditem = true;
            listboxdata.Add(count, listboxitem);
            count++;
            listboxitem = new listbox();
            listboxitem.name = "Read " + name + " list";
            listboxdata.Add(count, listboxitem);
            count++;
            return count;
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)");
            client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
            client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);

            #region Make to-do list

            int count = 0;
            count = addtodo(count, main_class.WinPackMan_DataURL + "?type=packages", "Cache/packages.list", "packages");
            count = addtodo(count, main_class.WinPackMan_DataURL + "?type=category", "Cache/category.list", "category");
            foreach (String lang in main_class.config.Language)
            {
                count = addtodo(count, main_class.WinPackMan_DataURL + "?type=installdata&language=" + lang, "Cache/pack_" + lang + ".list", main_class.Lang_2toEng[lang]);
            }

            listboxdata[0].state = "Downloading";
            startdownload();
            #endregion

            #region Read data
            count = 1;

            main_class.Softwarelist.Clear();
            main_class.NameToID.Clear();

            while (listboxdata[count - 1].state != "Done") System.Threading.Thread.Sleep(10);
            listboxdata[count].state = "Reading";
            #region Load packages list
            String[] packages = File.ReadAllLines("Cache/packages.list");
            foreach (String package in packages)
            {
                String[] info = package.Split(";".ToCharArray());
                Software newItem = new Software();

                newItem.packageID = info[PACK_ID];
                newItem.Name = info[PACK_NAME];
                newItem.categoryID = info[PACK_CATEGORY];
                newItem.Version = info[PACK_VERSION];
                newItem.Description = info[PACK_DESCRIPTION].Replace("%%", "\n");
                newItem.filetype = info[PACK_FILETYPE];
                newItem.VersionType = info[PACK_VERSIONTYPE].Replace("%%", "\n");
                if (info[PACK_DEPENDENCY] != "")
                {
                    String[] dependencies = info[PACK_DEPENDENCY].Split(",".ToCharArray());
                    newItem.Dependency = new int[dependencies.Length];
                    for (int i = 0; i < dependencies.Length; i++) newItem.Dependency[i] = int.Parse(dependencies[i]);
                }
                main_class.Softwarelist.Add(Int32.Parse(info[PACK_ID]), newItem);
                main_class.NameToID.Add(info[PACK_NAME], Int32.Parse(info[PACK_ID]));
            }
            #endregion
            listboxdata[count].state = "Done";
            count = count + 2;
            while (listboxdata[count - 1].state != "Done") System.Threading.Thread.Sleep(10);
            listboxdata[count].state = "Reading";
            #region Load category
            main_class.categoryID.Clear();
            main_class.categoryID.Add("ALL", -1);
            packages = File.ReadAllLines("Cache/category.list");
            foreach (String package in packages)
            {
                String[] info = package.Split(";".ToCharArray());
                main_class.categoryID.Add(info[1], Int32.Parse(info[0]));
            }
            #endregion
            listboxdata[count].state = "Done";
            count = count + 2;
            #region Load language data
            foreach (String language in main_class.config.Language)
            {
                while (listboxdata[count - 1].state != "Done") System.Threading.Thread.Sleep(10);
                listboxdata[count].state = "Reading";
                packages = File.ReadAllLines("Cache/pack_" + language + ".list");
                String[] filename;
                foreach (String package in packages)
                {
                    String[] info = package.Split(";".ToCharArray());
                    if (main_class.Softwarelist.ContainsKey(Int32.Parse(info[LANG_MEMBEROF_PACK])))
                    {
                        Software app = main_class.Softwarelist[Int32.Parse(info[LANG_MEMBEROF_PACK])];
                        InstallLanguage newItem = new InstallLanguage();
                        newItem.URL = info[LANG_FILEURL];
                        newItem.Arguments = info[LANG_INSTALLARGUMENTS];
                        newItem.MD5 = info[LANG_FILEMD5];
                        filename = info[LANG_FILEURL].Split("/=".ToCharArray());
                        newItem.Filename = filename[filename.Count() - 1];
                        if (info[LANG_INSTALLED] != "")
                        {
                            bool installed = progammainstalled(info[LANG_INSTALLED], info[LANG_ARCHITECTURE]);
                            if (installed)
                            {
                                if (app.Installed != "") app.Installed += "/";
                                app.Installed += language + " " + info[LANG_ARCHITECTURE];
                            }
                        }
                        if (info[LANG_ARCHITECTURE] == "x86")
                        {
                            app.x86.available = true;
                            app.x86.Language.Add(language, newItem);
                        }
                        if (info[LANG_ARCHITECTURE] == "x64")
                        {
                            app.x64.available = true;
                            app.x64.Language.Add(language, newItem);
                        }
                    }
                }
                listboxdata[count].state = "Done";
                count = count + 2;
            }
            #endregion


            #endregion
        }

        bool progammainstalled(String location, String architecture)
        {
            location = location.Replace("%SD", Environment.GetEnvironmentVariable("SystemDrive"));
            location = location.Replace("%AD", Environment.GetEnvironmentVariable("APPDATA"));
            if ((main_class.OS_Bits == "x64"))
                if (File.Exists(location.Replace("%PF", Environment.GetEnvironmentVariable("ProgramFiles(x86)")))) return true;
            return File.Exists(location.Replace("%PF", Environment.GetEnvironmentVariable("ProgramFiles")));
        }

        void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            Downloadlistdata[0].downloadstate = e.ProgressPercentage;
        }

        void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            startdownload();
        }

        void startdownload()
        {
        Complete:
            if (downloading != -2)
            {
                listboxdata[downloading].state = "Done";
                Downloadlistdata[downloading].downloadstate = 100;
            }
            downloading = downloading + 2;
            if (Downloadlistdata.ContainsKey(downloading))
            {
                listboxdata[downloading].state = "Downloading";
                if (!load || !File.Exists(Downloadlistdata[downloading].filename)) client.DownloadFileAsync(Downloadlistdata[downloading].URL, Downloadlistdata[downloading].filename);
                else goto Complete;
            }
        }

        public class downloadlist
        {
            public Uri URL;
            public string filename = "";
            public int downloadstate = 0;
        }

        public class listbox
        {
            public bool downloaditem = false;
            public string name = "";
            public string state = "Waiting";
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (LSTdetails.Items.Count != listboxdata.Count)
            {
                LSTdetails.Items.Clear();
                foreach (listbox item in listboxdata.Values)
                    LSTdetails.Items.Add(item.name).SubItems.Add(item.state);
            }
            int progress = 0;
            foreach (int item in listboxdata.Keys)
            {
                if (listboxdata[item].downloaditem) progress += Downloadlistdata[item].downloadstate;
                else if (listboxdata[item].state == "Done") progress += 100;
                if (LSTdetails.Items[item].SubItems[1].Text != listboxdata[item].state)
                    LSTdetails.Items[item].SubItems[1].Text = listboxdata[item].state;
            }
            if (progress != progressI.Value)
            {
                progressI.Maximum = listboxdata.Count * 100;
                progressI.Value = progress;
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            main_class.lastupdate = DateTime.Now.ToLongTimeString();
            main_class.updatetime = (DateTime.Now - start).Milliseconds.ToString();
            Close();
        }

    }
}
